package com.xmh.datasource.demo.config;

import com.alibaba.fastjson.JSON;
import com.xmh.datasource.demo.vo.DataSourceConfigVo;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;

import javax.persistence.EntityManagerFactory;
import java.util.HashMap;
import java.util.Map;

@Configuration
@EntityScan(basePackages = "com.xmh.datasource.demo.entity")
public class SqlEntityMapping {

    @Autowired
    private DataSourceProperties dataSourceProperties;

    @Bean("routingDataSource")
    public AbstractRoutingDataSource routingDataSource() {
        Map<Object, Object> targetDataSources = new HashMap<>();
        SqlDataSourceRouter sqlDataSourceRouter = new SqlDataSourceRouter();

        for (Map.Entry<String, Map<String, Object>> entry : this.dataSourceProperties.getMapping().entrySet()) {
            String toJSONString = JSON.toJSONString(entry.getValue());

            DataSourceConfigVo dataSourceConfigVo = JSON.parseObject(toJSONString, DataSourceConfigVo.class);

            HikariConfig hikariConfig = new HikariConfig();

            hikariConfig.setAutoCommit(false);

            hikariConfig.setJdbcUrl(dataSourceConfigVo.getDatasource().getUrl());
//            hikariConfig.setDriverClassName();
            hikariConfig.setUsername(dataSourceConfigVo.getDatasource().getUsername());
            hikariConfig.setPassword(dataSourceConfigVo.getDatasource().getPassword());

            hikariConfig.setConnectionTimeout(30000L);
            hikariConfig.setConnectionTestQuery("select 1");
            hikariConfig.setMaximumPoolSize(10);

            HikariDataSource hikariDataSource = new HikariDataSource(hikariConfig);

            targetDataSources.put(dataSourceConfigVo.getRoutingName(), hikariDataSource);
        }
        sqlDataSourceRouter.setDefaultTargetDataSource(targetDataSources.get(this.dataSourceProperties.getDefaultSetting()));
        sqlDataSourceRouter.setTargetDataSources(targetDataSources);
        return sqlDataSourceRouter;
    }

    @Bean(name = "entityManagerFactoryBean")
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(EntityManagerFactoryBuilder entityManagerFactoryBuilder) {
        return entityManagerFactoryBuilder.dataSource(routingDataSource())
                .packages(this.dataSourceProperties.getEntityPath())
                .build();
    }

    @Primary
    @Bean(name = "entityManagerFactory")
    public EntityManagerFactory entityManagerFactory(EntityManagerFactoryBuilder builder) {
        return this.entityManagerFactoryBean(builder).getObject();
    }

    @Primary
    @Bean(name = "transactionManager")
    public PlatformTransactionManager transactionManager(EntityManagerFactoryBuilder builder) {
        return new JpaTransactionManager(entityManagerFactory(builder));
    }

    @Bean
    public JdbcTemplate getJdbcTemplate() {
        return new JdbcTemplate(routingDataSource());
    }

//    @Bean
//    @ConditionalOnMissingBean
//    public HealthIndicator gld(JdbcTemplate jdbcTemplate, DataSourceProperties dataSourceProperties) {
//        return new JdbcHealthIndicator(jdbcTemplate, dataSourceProperties);
//    }


}
